#include "wifi_app.h"

// const 保证不可以修改 并且放置在flash 在函数调用的使用直接从flash引用 而不是在栈中复制一遍
// 通常在嵌入式开发中，存储固定配置信息时，数组形式（[]）更常用，可读性和安全性更高。
const static char g_mqttUserName[] = "board1&k0tp7kBek08";
const static char g_mqttPwd[] = "4f777d27c5a22d090d53e47ae8f8b814d129ce64c1bf8bb07529948523e7bf16";
const static char g_mqttUrl[] = "iot-06z00c3kqsjgy5d.mqtt.iothub.aliyuncs.com";
const static char g_mqttClientId[] = "k0tp7kBek08.board1|securemode=2\\,signmethod=hmacsha256\\,timestamp=1708571611329|";
const static char g_mqttTopic[] = "/sys/k0tp7kBek08/board1/thing/event/property/post";  // board1对应deviceName，设备名称

// static char* WifiName = "安瑞的iPhone";
// static char* WifiPassWord = "anrui723806";
static char* WifiName = "你猜猜";
static char* WifiPassWord = "18340899140";

/*需要发送的命令的数据*/
static const AtCmdInfo_s WIFIATCmdArr[] = {
    {
        .cmd = "ATE0\r\n",
        .rsp = "OK",
        .timeoutMs = 1000,
        .maxRetryTimes = 1,
    },// 关闭回显
    {
        .cmd = "AT+CWMODE=1\r\n",
        .rsp = "OK",
        .timeoutMs = 1000,
        .maxRetryTimes = 1,
    },// 设置为客户端模式
    {
        .cmd = "AT+CWJAP=\"%s\",\"%s\"\r\n",
        .rsp = "OK",
        .timeoutMs = 15000,
        .maxRetryTimes = 2,
    },// 连接热点的
    {
         .cmd = "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n",
         .rsp = "OK",
         .timeoutMs = 300,
         .maxRetryTimes = 1,
    },// 配置用户名等
    {
         .cmd = "AT+MQTTCONNCFG=0,0,0,\"\",\"\",0,0\r\n",
         .rsp = "OK",
         .timeoutMs = 1000,
         .maxRetryTimes = 1,
    },// 设置 MQTT 连接属性 连接保持时间   设置为0时 默认为120s 实际证明 并没有起作用 设置其他值 也没有起作用
    {
          .cmd = "AT+MQTTCONN=0,\"%s\",1883,0\r\n",
          .rsp = "OK",
          .timeoutMs = 2000,
          .maxRetryTimes = 2,
    },// 连接 MQTT Broker 不设置自动重连 因为自动重连的时间为15s
    {
        .cmd = "AT+MQTTPUB=0,\"%s\",\"{\\\"params\\\": {\\\"temp\\\": %.1f}}\",0,0\r\n",
        .rsp = "OK",
        .timeoutMs = 500,
        .maxRetryTimes = 1,
    },// 发布消息
    {
        .cmd = "AT+MQTTCLEAN=0\r\n",
        .rsp = "OK",
        .timeoutMs = 10000,
        .maxRetryTimes = 0,
    },// 清理配置消息

};

/**
 * @desc  : AT发送命令处理
 * @date  : 2025-08-12
 * @author: AnRui
 * @param : cmd - {参数说明}:
 * @param : rsp - {参数说明}:
 * @param : timeoutMs - {参数说明}:
 * @return: WifiComdState_e
 * @note  : 使用状态机的方式:
 *          发送状态: 等待命令返回  命令发送成功  命令发送失败
 */
static WifiCmdState_e  WifiCmdHandle(AtCmdInfo_s* commandInfo, uint8_t ResetToDefault) {
    // 保存命令返回数据的指针
    char* cmdReturnData;
    static uint32_t  current_retry_times = 0;
    static uint64_t  current_send_times = 0;
    static WifiCmdState_e current_cmd_status = WIFI_CMD_SEND;
    if (ResetToDefault) {
        current_retry_times = 0;
        current_send_times = 0;
        current_cmd_status = WIFI_CMD_SEND;
        return current_cmd_status;
    }
    switch (current_cmd_status) {
    case WIFI_CMD_SEND:
        WIFIClearRecvDataBuf();
        SendDataToWIFI(commandInfo->cmd);
        current_send_times = GetSysRunTime();
        current_cmd_status = WIFI_CMD_WAIT;
        break;
    case WIFI_CMD_WAIT:
        // 检测是否超时
        if ((GetSysRunTime() - current_send_times) > commandInfo->timeoutMs) {
            current_cmd_status = WIFI_CMD_RETRY;
        } else {
            // 没有超时就去获取一次返回值
            cmdReturnData = GetDataFromWIFI();
            if (cmdReturnData == NULL) return current_cmd_status;;
            if (strstr(cmdReturnData, "ERROR") != NULL) {
                current_retry_times = 0;
                current_send_times = 0;
                current_cmd_status = WIFI_CMD_SEND;
                return WIFI_CMD_FAIL;
            }
            if (strstr(cmdReturnData, commandInfo->rsp) != NULL) {
                current_retry_times = 0;
                current_send_times = 0;
                current_cmd_status = WIFI_CMD_SEND;
                return WIFI_CMD_SUCCESS;
            };
        }
        break;
    case WIFI_CMD_RETRY:
        if (current_retry_times < commandInfo->maxRetryTimes) {
            current_retry_times++;
            current_cmd_status = WIFI_CMD_SEND;
        } else {
            current_retry_times = 0;
            current_send_times = 0;
            current_cmd_status = WIFI_CMD_SEND;
            return WIFI_CMD_FAIL;
        }
        break;
    default:
        break;
    }
    return current_cmd_status;
}


/**
 * @desc  : 清理临时缓冲区
 * @date  : 2025-08-25
 * @author: AnRui
 * @param : buffer - {参数说明}:
 * @param : size - {参数说明}:
 * @note  :
 */
static void  ClearTmpCmdBuffer(char* buffer, int size) {
    memset(buffer, 0, size);
}
/**
 * @desc  : wifi连接 发送数据的任务
 * @date  : 2025-08-18
 * @author: AnRui
 * @note  :
 *          初始化 ->AT通信检查 失败进入硬件复位 超过一次 就返回模块错误
 *                              成功进入连接热点状态
 *                  连接热点状态 失败进入AT通信检查
 *                               进入连接MQTT
 *                 连接MQTT    失败进入AT通信检查
 *                             成功进入云平台通信
 *                 云平台通信   失败 进入AT通信检查
 *                     成功发送数据到云端
 *
 *
 * 自动重连需要15s
 */
void WifiNetWorkTask() {
    // 记录联网发送数据的流程处于阶段
    static  WifiWorkState_t current_connect_status = WIFI_AT_MODULE_CHECK_1_STATUS;
    // 记录当前硬件复位的次数
    static uint8_t hard_reset_times = 0;
    // 记录发送消息的时间
    static uint64_t pub_message_time = 0;
    // 临时保存当前命令
    static AtCmdInfo_s  current_cmd_info;
    // 拼接命令使用的临时缓冲区
    static char tmp_cmd_buffer[256] = { 0 };
    // 保存命令结果
    static WifiCmdState_e cmd_result;
    // 根据当前的流程 做不同的处理
    switch (current_connect_status) {
        // AT通信检查1的状态: 关闭回显
    case WIFI_AT_MODULE_CHECK_1_STATUS:
        current_cmd_info = WIFIATCmdArr[CMD_IDX_CLOSE_ECHO];
        cmd_result = WifiCmdHandle(&current_cmd_info, 0);
        if (cmd_result == WIFI_CMD_SUCCESS) {
            current_connect_status = WIFI_AT_MODULE_CHECK_2_STATUS;
        } else if (cmd_result == WIFI_CMD_FAIL) {
            current_connect_status = WIFI_HARD_RESET_STATUS;
        }
        break;
        // AT通信检查2的状态: 设置模块的设置STA模式为 Station 模式(客户端模式) 用于连接到无线路由器
    case WIFI_AT_MODULE_CHECK_2_STATUS:
        current_cmd_info = WIFIATCmdArr[CMD_IDX_SET_STA];
        cmd_result = WifiCmdHandle(&current_cmd_info, 0);
        if (cmd_result == WIFI_CMD_SUCCESS) {
            current_connect_status = WIFI_HOT_POINT_CONN_STATUS;
        } else if (cmd_result == WIFI_CMD_FAIL) {
            current_connect_status = WIFI_HARD_RESET_STATUS;
        }
        break;
        // 连接热点
    case WIFI_HOT_POINT_CONN_STATUS:
        current_cmd_info = WIFIATCmdArr[CMD_IDX_CONN_AP];
        // 清理临时命令缓冲区
        ClearTmpCmdBuffer(tmp_cmd_buffer, 256);
        // 拼接命令
        sprintf(tmp_cmd_buffer, current_cmd_info.cmd, WifiName, WifiPassWord);
        current_cmd_info.cmd = tmp_cmd_buffer;
        cmd_result = WifiCmdHandle(&current_cmd_info, 0);
        if (cmd_result == WIFI_CMD_SUCCESS) {
            current_connect_status = WIFI_MQTT_CONFIG_STATUS;
        } else if (cmd_result == WIFI_CMD_FAIL) {
            current_connect_status = WIFI_AT_MODULE_CHECK_1_STATUS;
        }
        break;
        // 配置MQTT
    case WIFI_MQTT_CONFIG_STATUS:
        current_cmd_info = WIFIATCmdArr[CMD_IDX_MQTT_CONF];
        // 清理临时命令缓冲区
        ClearTmpCmdBuffer(tmp_cmd_buffer, 256);
        sprintf(tmp_cmd_buffer, current_cmd_info.cmd, g_mqttClientId, g_mqttUserName, g_mqttPwd);
        current_cmd_info.cmd = tmp_cmd_buffer;
        cmd_result = WifiCmdHandle(&current_cmd_info, 0);
        if (cmd_result == WIFI_CMD_SUCCESS) {
            current_connect_status = WIFI__MQTT_CONN_CONF_STATUS;
        } else if (cmd_result == WIFI_CMD_FAIL) {
            current_connect_status = WIFI_AT_MODULE_CHECK_1_STATUS;
        }
        break;
    case   WIFI__MQTT_CONN_CONF_STATUS:
        current_cmd_info = WIFIATCmdArr[CMD_IDX_CONN_CONF];
        cmd_result = WifiCmdHandle(&current_cmd_info, 0);
        if (cmd_result == WIFI_CMD_SUCCESS) {
            current_connect_status = WIFI_MQTT_CONN_BROKER_STATUS;
        } else if (cmd_result == WIFI_CMD_FAIL) {
            current_connect_status = WIFI_AT_MODULE_CHECK_1_STATUS;
        }
        break;
        // 连接MQTT BROKER
    case WIFI_MQTT_CONN_BROKER_STATUS:
        current_cmd_info = WIFIATCmdArr[CMD_IDX_MQTT_BROKER];
        // 清理临时命令缓冲区
        ClearTmpCmdBuffer(tmp_cmd_buffer, 256);
        sprintf(tmp_cmd_buffer, current_cmd_info.cmd, g_mqttUrl);
        current_cmd_info.cmd = tmp_cmd_buffer;
        cmd_result = WifiCmdHandle(&current_cmd_info, 0);
        if (cmd_result == WIFI_CMD_SUCCESS) {
            current_connect_status = WIFI_PUB_MESSAGE_STATUS;
        } else if (cmd_result == WIFI_CMD_FAIL) {
            current_connect_status = WIFI_AT_MODULE_CHECK_1_STATUS;
        }
        break;
        // 发布消息
    case WIFI_PUB_MESSAGE_STATUS:
        // WIFI_SEND_MESSAGE_PERIOD 周期发送一次
        if (cmd_result == WIFI_CMD_SUCCESS && pub_message_time > 0 && (GetSysRunTime() - pub_message_time) < WIFI_SEND_MESSAGE_PERIOD) {
            break;
        }
        if (strstr(GetDataFromWIFI(), "+MQTTDISCONNECTED")) {
            WIFIClearRecvDataBuf();
            current_connect_status = WIFI_RECONNECT_CLEAN_INFO_STATUS;  // 跳转到发送状态
            WifiCmdHandle(NULL, 1);
            pub_message_time = 0;
            break;
        }
        current_cmd_info = WIFIATCmdArr[CMD_IDX_PUB_MESSAGE];
        // 清理临时命令缓冲区
        ClearTmpCmdBuffer(tmp_cmd_buffer, 256);
        sprintf(tmp_cmd_buffer, current_cmd_info.cmd, g_mqttTopic, 1.2);
        current_cmd_info.cmd = tmp_cmd_buffer;
        //  处理发送
        cmd_result = WifiCmdHandle(&current_cmd_info, 0);
        // 成功/失败处理（保留）
        if (cmd_result == WIFI_CMD_FAIL) {
            pub_message_time = 0;
            current_connect_status = WIFI_MQTT_CONN_BROKER_STATUS;
        } else if (cmd_result == WIFI_CMD_SUCCESS) {
            pub_message_time = GetSysRunTime(); // 更新时间戳
        }
        break;
        //重新连接之清理配置信息
    case WIFI_RECONNECT_CLEAN_INFO_STATUS:
        current_cmd_info = WIFIATCmdArr[CMD_IDX_CLEAN_INFO];
        cmd_result = WifiCmdHandle(&current_cmd_info, 0);
        if (cmd_result == WIFI_CMD_FAIL) {
            current_connect_status = WIFI_AT_MODULE_CHECK_1_STATUS;
        } else if (cmd_result == WIFI_CMD_SUCCESS) {
            current_connect_status = WIFI_MQTT_CONFIG_STATUS;
        }
        break;
        //硬件复位
    case WIFI_HARD_RESET_STATUS:
        if (hard_reset_times >= WIFI_HARD_RESET_TIMES) {
            current_connect_status = WIFI_MODULE_ERROR_STATUS;//模块错误    
        } else {
            hard_reset_times++;
            WIFIHardReset();
            current_connect_status = WIFI_AT_MODULE_CHECK_1_STATUS;
        }
        break;
        //模块错误
    case WIFI_MODULE_ERROR_STATUS:
        printf("moduel error \r\n");
        break;
    default:
        break;
    }
}
